Add sysroot.bootloader repo config key
authorRobert Fairley <rfairley@redhat.com>
Thu, 14 Feb 2019 21:18:01 +0000 (16:18 -0500)
committerAtomic Bot <atomic-devel@projectatomic.io>
Fri, 1 Mar 2019 21:20:35 +0000 (21:20 +0000)
The sysroot.bootloader key configures the bootloader
that OSTree uses when deploying a sysroot. Having this key
allows specifying behavior not to use the default bootloader
backend code, which is preferable when creating a first
deployment from the sysroot (#1774).

As of now, the key can take the values "auto" or "none". If
the key is not given, the value defaults to "auto".

"auto" causes _ostree_sysroot_query_bootloader() to be used
when writing a new deployment, which is the original behavior
that dynamically detects which bootloader to use.

"none" avoids querying the bootloader dynamically. The BLS
config fragments are still written to
sysroot/boot/loader/entries for use by higher-level software.

More values can be supported in future to specify a single
bootloader, different behavior for the bootloader code, or
a list of bootloaders to try.

Resolves: #1774

Closes: #1814
Approved by: jlebon

Makefile-tests.am
man/ostree.repo-config.xml
src/libostree/ostree-repo-private.h
src/libostree/ostree-repo.c
src/libostree/ostree-repo.h
src/libostree/ostree-sysroot-deploy.c
tests/libtest.sh
tests/test-admin-deploy-none.sh [new file with mode: 0755]

index 417a304a42d2bad4bc011b1ca463c153444b77a5..2c0916f6204576983f5b91032f369eb06ae0b42b 100644 (file)
@@ -102,6 +102,7 @@ _installed_or_uninstalled_test_scripts = \
        tests/test-admin-deploy-etcmerge-cornercases.sh \
        tests/test-admin-deploy-uboot.sh \
        tests/test-admin-deploy-grub2.sh \
+       tests/test-admin-deploy-none.sh \
        tests/test-admin-deploy-bootid-gc.sh \
        tests/test-admin-instutil-set-kargs.sh \
        tests/test-admin-upgrade-not-backwards.sh \
index 618b524b695e61aa878acba0d84b93626885ee6d..90ac9083996a9b2d43bc37a5163b1e0d98d279a3 100644 (file)
@@ -109,22 +109,22 @@ Boston, MA 02111-1307, USA.
         ensure files are on stable storage when performing operations
         such as commits, pulls, and checkouts.  Defaults to
         <literal>true</literal>.</para>
-       <para>
-         If you disable fsync, OSTree will no longer be robust
-         against kernel crashes or power loss.
-       </para>
-       <para>
-         You might choose to disable this for local development
-         repositories, under the assumption they can be recreated from
-         source.  Similarly, you could disable for a mirror where you could
-         re-pull.
-       </para>
-       <para>
-         For the system repository, you might choose to disable fsync
-         if you have uninterruptable power supplies and a well tested
-         kernel.
-       </para>
-       </listitem>
+        <para>
+          If you disable fsync, OSTree will no longer be robust
+          against kernel crashes or power loss.
+        </para>
+        <para>
+          You might choose to disable this for local development
+          repositories, under the assumption they can be recreated from
+          source.  Similarly, you could disable for a mirror where you could
+          re-pull.
+        </para>
+        <para>
+          For the system repository, you might choose to disable fsync
+          if you have uninterruptable power supplies and a well tested
+          kernel.
+        </para>
+        </listitem>
       </varlistentry>
 
       <varlistentry>
@@ -333,6 +333,42 @@ Boston, MA 02111-1307, USA.
 
   </refsect1>
 
+  <refsect1>
+    <title>[sysroot] Section Options</title>
+
+    <para>
+      Options for the sysroot, which contains the OSTree repository,
+      deployments, and stateroots.  The following entries are defined:
+    </para>
+
+    <variablelist>
+
+      <varlistentry>
+        <term><varname>bootloader</varname></term>
+        <listitem><para>Configure the bootloader that OSTree uses when
+        deploying the sysroot.  This may take the values
+        <literal>bootloader=none</literal> or <literal>bootloader=auto</literal>.
+        Default is <literal>auto</literal>.
+        </para>
+        <para>
+          If <literal>none</literal>, then OSTree will generate only BLS (Boot
+          Loader Specification) fragments in <literal>sysroot/boot/loader/entries/</literal>
+          for the deployment.
+        </para>
+        <para>
+          If <literal>auto</literal>, then in addition to generating BLS
+          fragments, OSTree will dynamically check for the existence of grub2,
+          uboot, and syslinux bootloaders.  If one of the bootloaders is found,
+          then OSTree will generate a config for the bootloader found.  For
+          example, <literal>grub2-mkconfig</literal> is run for the grub2 case.
+        </para>
+        </listitem>
+      </varlistentry>
+
+    </variablelist>
+
+  </refsect1>
+
   <refsect1>
     <title>/etc/ostree/remotes.d</title>
 
index 40be72633d8905f98a351b8cf6c6f222caf1dc26..6bc74c2d23f864998acf6f13e56f2ea7e584b13b 100644 (file)
@@ -169,6 +169,7 @@ struct OstreeRepo {
   guint64 payload_link_threshold;
   gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */
   gchar **repo_finders;
+  gchar *bootloader; /* Configure which bootloader to use. */
 
   OstreeRepo *parent_repo;
 };
index a71f3bdaff41e8d1c57bc64dcecbfa581a414d03..003365031ccb1e68b24c5b098592ba3098e1be72 100644 (file)
@@ -3113,6 +3113,32 @@ reload_remote_config (OstreeRepo          *self,
   return TRUE;
 }
 
+static gboolean
+reload_sysroot_config (OstreeRepo          *self,
+                       GCancellable        *cancellable,
+                       GError             **error)
+{
+  { g_autofree char *bootloader = NULL;
+
+    if (!ot_keyfile_get_value_with_default_group_optional (self->config, "sysroot",
+                                                           "bootloader", "auto",
+                                                           &bootloader, error))
+      return FALSE;
+
+    /* TODO: possibly later add support for specifying a generic bootloader
+     * binary "x" in /usr/lib/ostree/bootloaders/x). See:
+     * https://github.com/ostreedev/ostree/issues/1719
+     * https://github.com/ostreedev/ostree/issues/1801
+     */
+    if (!(g_str_equal (bootloader, "auto") || g_str_equal (bootloader, "none")))
+      return glnx_throw (error, "Invalid bootloader configuration: '%s'", bootloader);
+
+    self->bootloader = g_steal_pointer (&bootloader);
+  }
+
+  return TRUE;
+}
+
 /**
  * ostree_repo_reload_config:
  * @self: repo
@@ -3131,6 +3157,8 @@ ostree_repo_reload_config (OstreeRepo          *self,
     return FALSE;
   if (!reload_remote_config (self, cancellable, error))
     return FALSE;
+  if (!reload_sysroot_config (self, cancellable, error))
+    return FALSE;
   return TRUE;
 }
 
@@ -6064,3 +6092,21 @@ ostree_repo_get_default_repo_finders (OstreeRepo *self)
 
   return (const gchar * const *)self->repo_finders;
 }
+
+/**
+ * ostree_repo_get_bootloader:
+ * @self: an #OstreeRepo
+ * 
+ * Get the bootloader configured. See the documentation for the
+ * "sysroot.bootloader" config key.
+ * 
+ * Returns: bootloader configuration for the sysroot
+ * Since: 2019.2
+ */
+const gchar *
+ostree_repo_get_bootloader (OstreeRepo   *self)
+{
+  g_return_val_if_fail (OSTREE_IS_REPO (self), NULL);
+
+  return self->bootloader;
+}
index 6e325b8b3020a4ff920a0ae620184b676db784a2..7eb983cfa0e0bd0e0430941f8b7aa6e5cdb47c0c 100644 (file)
@@ -115,6 +115,9 @@ gboolean      ostree_repo_set_collection_id (OstreeRepo   *self,
 _OSTREE_PUBLIC
 const gchar * const * ostree_repo_get_default_repo_finders (OstreeRepo   *self);
 
+_OSTREE_PUBLIC
+const gchar * ostree_repo_get_bootloader (OstreeRepo   *self);
+
 _OSTREE_PUBLIC
 GFile *       ostree_repo_get_path (OstreeRepo  *self);
 
index b16f65b3345bf3b54a049951cd6c576ddd116b15..ec9d1592acdbff977c5d1ce471e5f980aa0c989a 100644 (file)
@@ -2310,6 +2310,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot     *self,
   gboolean bootloader_is_atomic = FALSE;
   SyncStats syncstats = { 0, };
   g_autoptr(OstreeBootloader) bootloader = NULL;
+  const char *bootloader_config = NULL;
   if (!requires_new_bootversion)
     {
       if (!create_new_bootlinks (self, self->bootversion,
@@ -2342,8 +2343,22 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot     *self,
             return glnx_throw_errno_prefix (error, "Remounting /boot read-write");
         }
 
-      if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error))
-        return FALSE;
+      OstreeRepo *repo = ostree_sysroot_repo (self);
+
+      bootloader_config = ostree_repo_get_bootloader (repo);
+
+      g_debug ("Using bootloader configuration: %s", bootloader_config);
+
+      if (g_str_equal (bootloader_config, "auto"))
+        {
+          if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error))
+            return FALSE;
+        }
+      else if (g_str_equal (bootloader_config, "none"))
+        {
+          /* No bootloader specified; do not query bootloaders to run. */
+        }
+
       bootloader_is_atomic = bootloader != NULL && _ostree_bootloader_is_atomic (bootloader);
 
       /* Note equivalent of try/finally here */
@@ -2375,6 +2390,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot     *self,
     sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID),
                      "MESSAGE=%s", msg,
                      "OSTREE_BOOTLOADER=%s", bootloader ? _ostree_bootloader_get_name (bootloader) : "none",
+                     "OSTREE_BOOTLOADER_CONFIG=%s", bootloader_config,
                      "OSTREE_BOOTLOADER_ATOMIC=%s", bootloader_is_atomic ? "yes" : "no",
                      "OSTREE_DID_BOOTSWAP=%s", requires_new_bootversion ? "yes" : "no",
                      "OSTREE_N_DEPLOYMENTS=%u", new_deployments->len,
index f09f4a2c5270d8607ffa5fc26a2365cc2823f0d2..a737a9bb5af58f6fce0e953493b0d702b91c73be 100755 (executable)
@@ -355,6 +355,11 @@ setup_os_boot_grub2() {
     esac
 }
 
+setup_os_boot_configured_bootloader() {
+    bootloader_keyval=$1
+    ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set ${bootloader_keyval}
+}
+
 setup_os_repository () {
     mode=$1
     shift
@@ -448,6 +453,9 @@ EOF
         *grub2*)
         setup_os_boot_grub2 "${bootmode}"
             ;;
+        sysroot\.bootloader*)
+        setup_os_boot_configured_bootloader "${bootmode}"
+            ;;
     esac
 
     cd ${test_tmpdir}
diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh
new file mode 100755 (executable)
index 0000000..9094036
--- /dev/null
@@ -0,0 +1,52 @@
+#!/bin/bash
+#
+# Copyright (C) 2019 Robert Fairley <rfairley@redhat.com>
+#
+# SPDX-License-Identifier: LGPL-2.0+
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+set -euo pipefail
+
+. $(dirname $0)/libtest.sh
+
+# Exports OSTREE_SYSROOT so --sysroot not needed.
+setup_os_repository "archive" "sysroot.bootloader none"
+
+extra_admin_tests=1
+
+. $(dirname $0)/admin-test.sh
+
+# Test that the bootloader configuration "none" generates BLS config snippets.
+cd ${test_tmpdir}
+rm httpd osdata testos-repo sysroot -rf
+setup_os_repository "archive" "sysroot.bootloader none"
+${CMD_PREFIX} ostree pull-local --repo=sysroot/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime
+# Test grub2 does not get detected with bootloader configuration "none"
+# (see https://github.com/ostreedev/ostree/issues/1774)
+mkdir -p sysroot/boot/grub2 && touch sysroot/boot/grub2/grub.cfg
+${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmaster/x86_64-runtime > out.txt
+assert_file_has_content out.txt "Bootloader updated.*"
+assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO'
+assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel'
+assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs'
+echo "ok generate bls config on first deployment"
+
+# TODO: add tests to try setting with an unsupported bootloader config,
+# once https://github.com/ostreedev/ostree/issues/1827 is solved.
+# The tests should check that the following commands fail:
+#  ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set sysroot.bootloader unsupported_bootloader
+#  ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set sysroot.bootloader ""